package se.stabby.undersokning.webapp;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import se.stabby.undersok.interfaces.UtföraUndersökningService;
import se.stabby.undersok.model.*;
import se.stabby.undersok.model.inmemory.InMemoryPågåendeUndersökningRepository;
import se.stabby.undersok.model.inmemory.InMemoryResultatRepository;
import se.stabby.undersok.model.statics.StaticTolkningsReporitory;
import se.stabby.undersok.model.statics.StaticUndersökningRepository;
import se.stabby.undersok.repository.PågåendeUndersökningRepository;
import se.stabby.undersok.repository.ResultatRepository;
import se.stabby.undersok.repository.TolkningsReporitory;
import se.stabby.undersok.repository.UndersökningRepository;

import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * User: per.segersten
 * Date: 2014-06-25
 */
@Path("undersok")
public class Undersok {

    static Context context = new Context();

    @GET
    @Path("{id}")
    @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
    public Undersokning getUndersok(@PathParam("id") String id) {

        Undersökning undersok = hämtaUndersökningsId(id);

        return new Undersokning.Builder().setId(undersok.id.id).setBeskrivning(undersok.beskrivning).setNamn(undersok.namn).setFragor(frågor(undersok.frågor)).build();
    }

    @POST
    @Path("{id}/svar")
    @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
    public UndersokningResult postaSvar(@PathParam("id") String id, UndersokningSvar svaren) {
        // 1 kontrollera input - alla svar finns, svaralternativen är ok
        Undersökning undersökning = hämtaUndersökningsId(id);
        // 2. skapa pågående undersöking och peta in svaren
        PågåendeUndersökning dennaUndersökning = context.pågåendeUndersökningRepository.skapa(undersökning);
        dennaUndersökning = läggTillSvaren(svaren, undersökning, dennaUndersökning);
        // 3. analysera
        Resultat resultat = context.tolkningsReporitory.sök(undersökning.id).tolka(dennaUndersökning);
        // 4. skicka tillbaka svar
        return UndersokningResult.create().resultat(resultat.analys).undersokningsId(resultat.pågåendeUndersökningId.id).id(resultat.pågåendeUndersökningId.id).build();
    }

    private PågåendeUndersökning läggTillSvaren(UndersokningSvar svar, Undersökning undersökning, PågåendeUndersökning dennaUndersökning) {
        if (undersökning.frågor.size() != svar.getSvaren().size()) {
            throw new WebApplicationException(400);
        }
        for (int i = 0; i < svar.getSvaren().size(); i++) {
            Fråga fråga = undersökning.frågor.get(i);
            SvarDO svaret = svar.getSvaren().get(i);
            if (!svaret.getFradaId().equals(Long.toString(fråga.id.id))) {
                throw new WebApplicationException(400);
            }
            dennaUndersökning = dennaUndersökning.läggTillSvar(Svar.create().id(new SvarId(1)).fråga(fråga).pågåendeUndersökningsId(dennaUndersökning.id).build());
        }
        return dennaUndersökning;
    }


    private List<Fraga> frågor(ImmutableList<Fråga> frågor) {
        return frågor.stream().map(new Function<Fråga, Fraga>() {
            @Override
            public Fraga apply(Fråga f) {
                return new Fraga.Builder().setFraga(f.fråga).setId(f.id.id).setSvarsalternativ(f.svarsalternativ).build();
            }
        }).collect(Collectors.toList());
    }

    private Undersökning hämtaUndersökningsId(String id) {
        if (!context.map.containsKey(id)) {
            throw new WebApplicationException(404);
        }
        Undersökning undersok = context.undersökningRepository.sök(new UndersökningsId(context.map.get(id)));
        if (undersok == null) {
            throw new WebApplicationException(404);
        }
        return undersok;
    }


}


class Context {

    Map<String, Integer> map = ImmutableMap.of("semester", 1);

    UndersökningRepository undersökningRepository = createUndersökningRepository();
    PågåendeUndersökningRepository pågåendeUndersökningRepository = createPågåendeUndersökningRepository();
    ResultatRepository resultatRepository = createResultatRepository();
    TolkningsReporitory tolkningsReporitory = createTolkningsReporitory();
    UtföraUndersökningService service = new UtföraUndersökningService(undersökningRepository,
            pågåendeUndersökningRepository,
            resultatRepository,
            tolkningsReporitory);

    private TolkningsReporitory createTolkningsReporitory() {
        return new StaticTolkningsReporitory();
    }

    private ResultatRepository createResultatRepository() {
        return new InMemoryResultatRepository();
    }

    private PågåendeUndersökningRepository createPågåendeUndersökningRepository() {
        return new InMemoryPågåendeUndersökningRepository();
    }

    private UndersökningRepository createUndersökningRepository() {
        return new StaticUndersökningRepository();
    }

}
